package org.taobao.ibatiside.ui.wizard;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.Text;
import org.taobao.ibatiside.model.mapperv2.Mapperv2Factory;
import org.taobao.ibatiside.model.mapperv2.TypeAlias;
import org.taobao.ibatiside.ui.util.SqlmapFileDialog;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;

public class NewMapperFilePage extends WizardPage {
	private Text text_config;
	private Table table;
	private Text text_ns;
	private IFile configurationFile;
	private List<TypeAlias> aliases = new ArrayList<TypeAlias>();
	private IPath newMapperPath;
	private String namespace;
	private Text text;

	/**
	 * Create the wizard.
	 */
	public NewMapperFilePage() {
		super("newmapperpage");
		setTitle("New Mapper File");
		setDescription("Create new sqlmap file against to ibatis configuration");
	}
	public void setConfigurationFile(IFile configurationFile) {
		this.configurationFile = configurationFile;
	}
	public String getNamespace(){
		return namespace;
	}
	public List<TypeAlias> getAliases() {
		return aliases;
	}
	public IPath getNewMapperPath() {
		return newMapperPath;
	}

	/**
	 * Create contents of the wizard.
	 * @param parent
	 */
	public void createControl(Composite parent) {
		Composite container = new Composite(parent, SWT.NULL);

		setControl(container);
		container.setLayout(new GridLayout(1, false));
		
		Composite composite = new Composite(container, SWT.BORDER);
		composite.setLayout(new GridLayout(2, false));
		GridData gd_composite = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1);
		gd_composite.heightHint = 100;
		composite.setLayoutData(gd_composite);
		
		Label lblConfigurationFile = new Label(composite, SWT.NONE);
		lblConfigurationFile.setAlignment(SWT.RIGHT);
		lblConfigurationFile.setText("Configuration File");
		
		text_config = new Text(composite, SWT.BORDER | SWT.READ_ONLY);
		text_config.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
		
		Label lblSqlmapFile = new Label(composite, SWT.NONE);
		lblSqlmapFile.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
		lblSqlmapFile.setText("SQLMap File");
		
		text = new Text(composite, SWT.BORDER);
		text.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseDoubleClick(MouseEvent e) {
				SqlmapFileDialog dialog = new SqlmapFileDialog(getShell(), JavaCore.create(configurationFile.getProject()));
				if (newMapperPath != null) dialog.setResourcePath(newMapperPath);
				if (dialog.open() == SqlmapFileDialog.OK){
					newMapperPath =  dialog.getResourcePath();
					text.setText(newMapperPath.toString());
				}
			}
		});
		text.addModifyListener(new ModifyListener() {
			@Override
			public void modifyText(ModifyEvent e) {
				newMapperPath = new Path(text.getText());
				IResource new_res = ResourcesPlugin.getWorkspace().getRoot().findMember(newMapperPath);
				if (new_res != null){
					setErrorMessage("resource exists, please use a different name!");
					setPageComplete(false);
				}else{
					setPageComplete(true);
				}
			}
		});
		text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
		
		Label lblNamespace = new Label(composite, SWT.NONE);
		lblNamespace.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
		lblNamespace.setText("Namespace");
		
		text_ns = new Text(composite, SWT.BORDER);
		text_ns.addFocusListener(new FocusAdapter() {
			@Override
			public void focusLost(FocusEvent e) {
				namespace = text_ns.getText();
			}
		});
		
		Group grpTypeAlias = new Group(container, SWT.NONE);
		grpTypeAlias.setLayout(new GridLayout(1, false));
		GridData gd_grpTypeAlias = new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1);
		gd_grpTypeAlias.heightHint = 142;
		grpTypeAlias.setLayoutData(gd_grpTypeAlias);
		grpTypeAlias.setText("Type Alias");
		
		final TableViewer tableViewer = new TableViewer(grpTypeAlias, SWT.BORDER | SWT.FULL_SELECTION);
		table = tableViewer.getTable();
		table.addKeyListener(new KeyAdapter() {
			@Override
			public void keyReleased(KeyEvent e) {
				if (e.character == SWT.DEL){
					ISelection selection = tableViewer.getSelection();
					if (!selection.isEmpty())
						delete((TypeAlias) ((IStructuredSelection)selection).getFirstElement());
				}
			}

			private void delete(TypeAlias firstElement) {
				aliases.remove(firstElement);
				tableViewer.remove(firstElement);
			}
		});
		table.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseDoubleClick(MouseEvent e) {
				int line_pos = e.y / table.getItemHeight();
				if (line_pos > table.getItemCount()){
					TypeAlias new_created = addOneAlias();
					tableViewer.add(new_created);
					int column_idx = e.x > table.getColumn(0).getWidth() ? 1 : 0;
					tableViewer.editElement(new_created, column_idx);
				}
			}

			private TypeAlias addOneAlias() {
				TypeAlias ta = Mapperv2Factory.eINSTANCE.createTypeAlias();
				ta.setAlias("Foo");
				ta.setType("java.lang.Object");
				aliases.add(ta);
				return ta;
			}
		});
		table.setHeaderVisible(true);
		table.setLinesVisible(true);
		table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));
		
		TableViewerColumn tableViewerColumn = new TableViewerColumn(tableViewer, SWT.NONE);
		tableViewerColumn.setEditingSupport(new EditingSupport(tableViewer) {
			protected boolean canEdit(Object element) {
				return true;
			}
			protected CellEditor getCellEditor(Object element) {
				return new TextCellEditor(table);
			}
			protected Object getValue(Object element) {
				return StringUtils.defaultString(((TypeAlias)element).getAlias());
			}
			protected void setValue(Object element, Object value) {
				//Alias is as primary key.
				String alias = (String)value;
				if (StringUtils.isNotBlank(alias) && noSameName(alias)){
					((TypeAlias)element).setAlias(alias);
					tableViewer.update(element, null);
				}
				
			}
		});
		tableViewerColumn.setLabelProvider(new ColumnLabelProvider() {
			public Image getImage(Object element) {
				return null;
			}
			public String getText(Object element) {
				return element == null ? "" : ((TypeAlias)element).getAlias();
			}
		});
		TableColumn tblclmnAlias = tableViewerColumn.getColumn();
		tblclmnAlias.setWidth(120);
		tblclmnAlias.setText("Alias");
		
		TableViewerColumn tableViewerColumn_1 = new TableViewerColumn(tableViewer, SWT.NONE);
		tableViewerColumn_1.setEditingSupport(new EditingSupport(tableViewer) {
			protected boolean canEdit(Object element) {
				return true;
			}
			protected CellEditor getCellEditor(Object element) {
				IJavaProject jp = JavaCore.create(configurationFile.getProject());
				return new TypeSelectionCellEditor(((TypeAlias)element).getType(), table, jp, IJavaSearchConstants.TYPE);
			}
			protected Object getValue(Object element) {
				String fqn = ((TypeAlias)element).getType();
				IJavaProject jp = JavaCore.create(configurationFile.getProject());
				if (null != fqn){
					try {
						return jp.findType(fqn);
					} catch (JavaModelException e) {
						e.printStackTrace();
					}
				}
				return null;
			}
			protected void setValue(Object element, Object value) {
				if (element != null && value != null){
					String fqn = ((IType)value).getFullyQualifiedName();
					((TypeAlias)element).setType(fqn);
					tableViewer.update(element, null);
				}
			}
		});
		tableViewerColumn_1.setLabelProvider(new ColumnLabelProvider() {
			public Image getImage(Object element) {
				return null;
			}
			public String getText(Object element) {
				return element == null ? "" : ((TypeAlias)element).getType();
			}
		});
		TableColumn tblclmnFullQualifiedType = tableViewerColumn_1.getColumn();
		tblclmnFullQualifiedType.setWidth(375);
		tblclmnFullQualifiedType.setText("Full Qualified Type");
		tableViewer.setContentProvider(new ArrayContentProvider());
		tableViewer.setInput(aliases);
		text_config.setText(configurationFile.getFullPath().toString());
	}
	protected boolean noSameName(String value) {
		for (TypeAlias ta : aliases){
			if (value.equals(ta.getAlias())){
				return false;
			}
		}
		return true;
	}
}
